﻿// 绘制直方图与大津算法的图像分割
//

#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

// 画出给定图像的灰度直方图
Mat imageHist(Mat src)
{
	Mat gray;
	cvtColor(src, gray, CV_RGB2GRAY);
	const int nimages = 1;//输入图像个数
	int channels[] = { 0 };//需要统计的通道的索引  若是彩色channels[] = {0,1,2}
	MatND hist;// 输出的目标直方图
	int dims = 1;//直方图的维度
	int histSize[] = { 256 }; //每个维度中，直方图数组的长度，量化成histSize个等级，即直条个数
	float hranges[] = { 0.0, 255.0 };//数组的数组，数据（像素的灰度值）的取值范围
	const float* ranges[] = { hranges };//一定要有const	
	calcHist(&gray, nimages, channels, Mat(), hist, dims, histSize, ranges);
	//【4】获取最大最小值	
	double minValue = 0;
	double maxValue = 0;
	minMaxLoc(hist, &minValue, &maxValue);
	//【5】绘制灰度图像一维直方图	
	Mat dstImage(histSize[0], histSize[0], CV_8U, Scalar(255));//256*256的白色底板
	int hpt = saturate_cast<int>(0.9 * histSize[0]);
	for (int i = 0; i < 256; i++)
	{
		float binValue = hist.at<float>(i);
		//统计数值的缩放，增强直方图的可视化		
		int realValue = saturate_cast<int>(binValue * hpt / maxValue);
		//在256*256的白色底板上画矩形		
		rectangle(dstImage, Point(i, histSize[0] - 1), Point(i + 1, histSize[0] - realValue), Scalar(10));
	}
	return dstImage;

}


int main()
{
	Mat imageRice = imread("E:\\VC_project\\figure\\rice.png");
	Mat image1 = imread("E:\\VC_project\\figure\\pic2.png");
	Mat image2 = imread("E:\\VC_project\\figure\\pic6.png");
	
	Mat riceHist, pic2Hist, pic6Hist, riceGray, pic2Gray, pic6Gray, riceOTSU, pic2OTSU, pic6OTSU;

	//对图像进行灰度化处理
	cvtColor(imageRice, riceGray, CV_BGR2GRAY);
	cvtColor(image1, pic2Gray, CV_BGR2GRAY);
	cvtColor(image2, pic6Gray, CV_BGR2GRAY);
	//调用函数绘制直方图
	riceHist = imageHist(imageRice);
	pic2Hist = imageHist(image1);
	pic6Hist = imageHist(image2);

	imshow("rice", imageRice);
	imshow("pic2", image1);
	imshow("pic6", image2);

	imshow("riceHist", riceHist);
	imshow("pic2Hist", pic2Hist);
	imshow("pic6Hist", pic6Hist);
	

	//使用大津算法分割图像
	threshold(riceGray, riceOTSU, 0, 255, CV_THRESH_OTSU);
	threshold(pic2Gray, pic2OTSU, 0, 255, CV_THRESH_OTSU);
	threshold(pic6Gray, pic6OTSU, 0, 255, CV_THRESH_OTSU);

	imshow("OTSU分割图像rice", riceOTSU);
	imshow("OTSU分割图像pic2", pic2OTSU);
	imshow("OTSU分割图像pic6", pic6OTSU);
	waitKey();
}


